package com.tangsm.spring.mvc.mybatis.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tangsm.spring.mvc.mybatis.dao.AppointmentDao;
import com.tangsm.spring.mvc.mybatis.dao.BookDao;
import com.tangsm.spring.mvc.mybatis.domain.dto.AppointExecution;
import com.tangsm.spring.mvc.mybatis.domain.entity.Appointment;
import com.tangsm.spring.mvc.mybatis.domain.entity.Book;
import com.tangsm.spring.mvc.mybatis.enums.AppointStateEnum;
import com.tangsm.spring.mvc.mybatis.exception.AppointException;
import com.tangsm.spring.mvc.mybatis.exception.NoNumberException;
import com.tangsm.spring.mvc.mybatis.exception.RepeatAppointException;
import com.tangsm.spring.mvc.mybatis.service.BookService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class BookServiceImpl implements BookService {

	private static final Logger logger = LoggerFactory.getLogger(BookServiceImpl.class);

	@Autowired
	private BookDao bookDao;

	@Autowired
	private AppointmentDao appointmentDao;

	/**
	 * 分页查询
	 * @param pageNum 页码
	 * @param pageSize 每页数
	 * @return 分页对象
	 */
	@Override
	public PageInfo<Book> page(int pageNum, int pageSize) {
		return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(this::getList);
	}

	public Book getById(long bookId) {
		return bookDao.queryById(bookId);
	}

	public List<Book> getList() {
		return bookDao.queryAll();
	}

	/**
	 * 使用注解控制事务方法的优点： 1.开发团队达成一致约定，明确标注事务方法的编程风格
	 * 2.保证事务方法的执行时间尽可能短，不要穿插其他网络操作，RPC/HTTP请求或者剥离到事务方法外部
	 * 3.不是所有的方法都需要事务，如只有一条修改操作，只读操作不需要事务控制
	 */
	@Transactional
	public AppointExecution appoint(long bookId, long studentId) {
		try {
			// 减库存
			int update = bookDao.reduceNumber(bookId);
			if (update <= 0) {// 库存不足
				throw new NoNumberException("no number");
			} else {
				// 执行预约操作
				int insert = appointmentDao.insertAppointment(bookId, studentId);
				if (insert <= 0) {// 重复预约
					throw new RepeatAppointException("repeat appoint");
				} else {// 预约成功
					Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);
					return new AppointExecution(bookId, AppointStateEnum.SUCCESS, appointment);
				}
			}
		} catch (NoNumberException | RepeatAppointException e1) {
			throw e1;
		} catch (Exception e) {
			final String message = e.getMessage();
			logger.error(message, e);
			// 所有编译期异常转换为运行期异常
			throw new AppointException("appoint inner error:" + message);
		}
	}

}
